package com.yuye.excel.easyexcel.handle;


import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.yuye.excel.annotation.ExcelImport;
import com.yuye.excel.base.ValidateExcelField;
import com.yuye.excel.base.dto.ExcelImportResult;
import com.yuye.excel.base.dto.FieldValidateDTO;
import com.yuye.excel.easyexcel.handle.listener.EasyExcelListener;
import com.yuye.excel.easyexcel.handle.vali.ExcelCheckManager;
import com.yuye.excel.springboot.ApplicationContextGetBeanHelper;

@Aspect
@Component
public class EasyExcelAspect {
	
	public static final ThreadLocal<String> threadLocal = new ThreadLocal<>();

    @Pointcut("@annotation(com.yuye.excel.annotation.ExcelImport)")
    public void annotationPoinCut(){}

    @Around("annotationPoinCut()")
    public Object after(ProceedingJoinPoint joinPoint) throws Throwable{
    	
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();
        String packageName = signature.getDeclaringTypeName();
        ExcelImport action = method.getAnnotation(ExcelImport.class);
        System.out.println("注解式拦截 ");
        threadLocal.set(packageName + "." + methodName);
        
        try {
        	Object[] args = joinPoint.getArgs();
            MultipartFile file = null;
            EasyExcelListener easyExcelListener = null;
            for (Object param : args) {
    			if(param instanceof MultipartFile) {
    				file = (MultipartFile) param;
    			}
    		}
            if(file == null) {
            	return joinPoint.proceed(args);
            }
            
            //系统判断 空/长度 （和 easyexcel 进行 合作） 添加一个class 
            Class paramClass = action.paramClass();
            //所有该类的 需要判断的 字段
            List<FieldValidateDTO> fieldValidateDTOList = getParamsName(paramClass, signature);
            //完成 获取 file 文件
            
            
            //根据文件和 fieldValidateDTOList 验证 + 转换
            try {
            	//业务判断 这需要加一个属性 是一个接口实现类
    			easyExcelListener = readExcel(fieldValidateDTOList, file, paramClass, action);
    		} catch (IOException e) {
    			e.printStackTrace();
    			throw new ExcelAnalysisException("文件读取异常");
    		}
            
            for (Object param : args) {
    			if(param instanceof ExcelImportResult) {
    				ExcelImportResult excelImportResult = (ExcelImportResult) param ;
    				excelImportResult.setEasyExcelListener(easyExcelListener);
    				param = excelImportResult;
    			}
    		}
            
            //返回给 一个属性中 ，然后 执行他的内部逻辑 （修改 失败/成功的list 数据）
            // 先获取 是全量/局部 插入
            
            //接口有一个方法是 insert list的 我调用插入到库
            
            //修改返回值 为 一个固定返回对象（file流  + 成功条数 + 失败条数）
            
    		return joinPoint.proceed(args);
		} finally {
			threadLocal.remove();
		}
        
		
        
        
        
    }
    //系统参数 验证 + 数据转换
    private EasyExcelListener readExcel(List<FieldValidateDTO> fieldValidateDTOList, MultipartFile file, Class paramClass
    		, ExcelImport action) throws IOException {
    	Class excelCheck = action.excelCheck();
    	String name = excelCheck.getName();
    	String beanName = name.substring(name.lastIndexOf(".") + 1, name.length());
    	//从springboot 中 获取 该Class 对象 
    	ExcelCheckManager excelCheckManager = (ExcelCheckManager) ApplicationContextGetBeanHelper.getBean(beanName);
    	EasyExcelListener easyExcelListener = new EasyExcelListener(excelCheckManager,
    			paramClass);	
		EasyExcel.read(file.getInputStream(), paramClass, easyExcelListener).doReadAll();
		System.out.println(easyExcelListener.getErrList());
		return easyExcelListener;
    }

    
    /**拿到在参数上加了该注解的参数名称*/
    private List<FieldValidateDTO> getParamsName(Class paramClass, MethodSignature signature) {
    	//key 类名+方法名   value为(filed   Validate对象)
    	Map<String, List<FieldValidateDTO>> map = new HashMap<>();
    	Field[] fields = paramClass.getDeclaredFields();
    	List<FieldValidateDTO> list = new ArrayList<>();
    	
        for(Field field : fields){
        	ValidateExcelField api = field.getAnnotation(ValidateExcelField.class);
            if(null != api){
            	//保存 当前属性名 和  Validate对象。    a字段 有这些判断 之后直接拿 
            	//之后 遍历取值 然后判断 不符合的放到 error中 成功的保存放到success List
            	FieldValidateDTO fieldValidateDTO = new FieldValidateDTO();
            	fieldValidateDTO.setFieldName(field.getName());
            	fieldValidateDTO.setValidateExcelField(api);
            	list.add(fieldValidateDTO);
            	
            }
        }
        map.put(signature.getName() + signature.getMethod().getName(), list);
        return list;
    }
    
    
    
}